package airwallex

import (
	"bytes"
	"context"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"github.com/goccy/go-json"
	"github.com/shopspring/decimal"
	"io/ioutil"
	"net/http"
	"simplifly-tech/payment/common"
	"simplifly-tech/payment/consts"
	"simplifly-tech/utility/db"
	"simplifly-tech/utility/log"
	"time"
)

type AirwallexService struct {
	Channel         consts.SysIncomeChannel
	IsSandbox       bool
	XClientId       string
	XApiKey         string
	PayServerKey    string
	RefundServerKey string
	TransactionRate decimal.Decimal
	Fee             decimal.Decimal
	FeeCurrency     string
	PayerOrgID      uint
	PayeeOrgID      uint
}

type RespToken struct {
	ExpiresAt string `json:"expires_at"`
	Token     string `json:"token"`
}

type SendCode string

const (
	SendCodeLogin           SendCode = "/api/v1/authentication/login"
	SendCodePay                      = "/api/v1/pa/payment_intents/create"
	SendCodeCreateCustomers          = "/api/v1/pa/customers/create"
	SendCodeCreateRefund             = "/api/v1/pa/refunds/create"
)

func (airwallexService *AirwallexService) Init(
	isSandbox bool,
	xClientId string,
	xApiKey string,
	payServerKey string,
	refundServerKey string,
	transactionRate decimal.Decimal,
	fee decimal.Decimal,
	feeCurrency string,
) {
	airwallexService.Channel = consts.SysIncomeChannelAirwallex
	airwallexService.IsSandbox = isSandbox
	airwallexService.XClientId = xClientId
	airwallexService.XApiKey = xApiKey
	airwallexService.PayServerKey = payServerKey
	airwallexService.RefundServerKey = refundServerKey
	airwallexService.TransactionRate = transactionRate
	airwallexService.Fee = fee
	airwallexService.FeeCurrency = feeCurrency
}

func (airwallexService *AirwallexService) getToken() (string, error) {
	cacheKey := common.GetAirWallexRedisAccessToken(airwallexService.XClientId)
	accessToken, err := db.GetRedisClient().Get(context.Background(), cacheKey).Result()
	if err == nil && accessToken != "" {
		return accessToken, err
	}
	client := &http.Client{
		Timeout: time.Second * 10,
	}

	req, err := http.NewRequest("POST", airwallexService.getHost()+string(SendCodeLogin), nil)
	if err != nil {
		log.Errorf(" (paypalService *PaypalService) Init()   req, err := http.NewRequest err %v", err)
		return "", err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-client-id", airwallexService.XClientId)
	req.Header.Set("x-api-key", airwallexService.XApiKey)

	resp, err := client.Do(req)
	if err != nil {
		log.Errorf(" (paypalService *PaypalService) Init()  err := client.Do(req)err %v", err)
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Errorf(" (paypalService *PaypalService) Init() getResponse ioutil.ReadAll err %v", err)
		return "", err
	}

	var respToken RespToken
	err = json.Unmarshal(body, &respToken)
	if err != nil {
		log.Errorf("【paypal】 json.Unmarshal(data, &authRespData) err:%v", err)
	}
	db.GetRedisClient().Set(context.Background(), cacheKey, respToken.Token, 20*time.Minute)
	return respToken.Token, nil
}

//func (service *AirwallexService) createCustomer(org *model.Organization) (string, error) {
//	reqData := CreateCustomerReq{
//		Address: &CreateCustomerAddress{
//			City:        "Beijing",
//			CountryCode: "CN",
//		},
//		BusinessName: org.Name,
//		//Email:              org.Email,
//		MerchantCustomerId: "cstt_" + fmt.Sprintf("%d", org.ID),
//		RequestId:          time.Now().String() + fmt.Sprintf("%d", agency.Id),
//	}
//	payResp, err := service.getResponse(SendCodeCreateCustomers, reqData, "")
//	if nil != err {
//		return "", err
//	}
//
//	var respData CreateCustomerResp
//	err = json.Unmarshal(payResp, &respData)
//	if err != nil {
//		log.Errorf("airwallex反序列化异常： %v", err)
//		return "", err
//	}
//
//	return respData.Id, nil
//}

func (service *AirwallexService) getResponse(sendCode string, origin any, method string) ([]byte, error) {

	params, err := json.Marshal(origin)
	if err != nil {
		log.Errorf("json编码失败：%v", err)
		return nil, err
	}
	token, err := service.getToken()
	if err != nil {
		return nil, err
	}

	sendDataHeader := map[string]string{
		"Content-Type":  "application/json",
		"Authorization": "Bearer " + token,
		"x-api-version": "2024-09-27",
	}
	formBytesReader := bytes.NewReader(params)
	if method == "" {
		method = "POST"
	}
	body, _, err := common.HttpRequest(service.getHost()+sendCode, method, sendDataHeader, formBytesReader)
	if err != nil {
		log.Errorf("请求失败：%v", err)
		return nil, err
	}

	return body, nil
}

func (service *AirwallexService) getHost() string {
	if !service.IsSandbox {
		return "https://api.airwallex.com"
	} else {
		return "https://api-demo.airwallex.com"
	}
}

func ComputeHMAC(secretKey, message string) string {
	// 创建一个 HMAC 对象并指定哈希算法为 SHA256
	h := hmac.New(sha256.New, []byte(secretKey))
	// 写入消息
	h.Write([]byte(message))
	// 计算签名并以十六进制返回
	return hex.EncodeToString(h.Sum(nil))
}
